{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ConversationBufferMemory\n",
    "\n",
    "이 메모리는 메시지를 저장한 다음 변수에 메시지를 추출할 수 있게 해줍니다.\n",
    "\n",
    "먼저 문자열로 추출할 수 있습니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.memory import ConversationBufferMemory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "memory = ConversationBufferMemory()\n",
    "memory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "memory.save_context(\n",
    "    inputs={\n",
    "        \"human\": \"안녕하세요, 비대면으로 은행 계좌를 개설하고 싶습니다. 어떻게 시작해야 하나요?\"\n",
    "    },\n",
    "    outputs={\n",
    "        \"ai\": \"안녕하세요! 계좌 개설을 원하신다니 기쁩니다. 먼저, 본인 인증을 위해 신분증을 준비해 주시겠어요?\"\n",
    "    },\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "memory"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "memory 의 `load_memory_variables({})` 함수는 메시지 히스토리를 반환합니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 'history' 키에 저장된 대화 기록을 확인합니다.\n",
    "print(memory.load_memory_variables({})[\"history\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`save_context(inputs, outputs)` 메서드를 사용하여 대화 기록을 저장할 수 있습니다.\n",
    "\n",
    "- 이 메서드는 `inputs`와 `outputs` 두 개의 인자를 받습니다.\n",
    "- `inputs`는 사용자의 입력을, `outputs`는 AI의 출력을 저장합니다.\n",
    "- 이 메서드를 사용하면 대화 기록이 `history` 키에 저장됩니다.\n",
    "- 이후 `load_memory_variables` 메서드를 사용하여 저장된 대화 기록을 확인할 수 있습니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# inputs: dictionary(key: \"human\" or \"ai\", value: 질문)\n",
    "# outputs: dictionary(key: \"ai\" or \"human\", value: 답변)\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"네, 신분증을 준비했습니다. 이제 무엇을 해야 하나요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"감사합니다. 신분증 앞뒤를 명확하게 촬영하여 업로드해 주세요. 이후 본인 인증 절차를 진행하겠습니다.\"\n",
    "    },\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2개의 대화를 저장합니다.\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"사진을 업로드했습니다. 본인 인증은 어떻게 진행되나요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"업로드해 주신 사진을 확인했습니다. 이제 휴대폰을 통한 본인 인증을 진행해 주세요. 문자로 발송된 인증번호를 입력해 주시면 됩니다.\"\n",
    "    },\n",
    ")\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"인증번호를 입력했습니다. 계좌 개설은 이제 어떻게 하나요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"본인 인증이 완료되었습니다. 이제 원하시는 계좌 종류를 선택하고 필요한 정보를 입력해 주세요. 예금 종류, 통화 종류 등을 선택할 수 있습니다.\"\n",
    "    },\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# history에 저장된 대화 기록을 확인합니다.\n",
    "print(memory.load_memory_variables({})[\"history\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 추가로 2개의 대화를 저장합니다.\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"정보를 모두 입력했습니다. 다음 단계는 무엇인가요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"입력해 주신 정보를 확인했습니다. 계좌 개설 절차가 거의 끝났습니다. 마지막으로 이용 약관에 동의해 주시고, 계좌 개설을 최종 확인해 주세요.\"\n",
    "    },\n",
    ")\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"모든 절차를 완료했습니다. 계좌가 개설된 건가요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"네, 계좌 개설이 완료되었습니다. 고객님의 계좌 번호와 관련 정보는 등록하신 이메일로 발송되었습니다. 추가적인 도움이 필요하시면 언제든지 문의해 주세요. 감사합니다!\"\n",
    "    },\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# history에 저장된 대화 기록을 확인합니다.\n",
    "print(memory.load_memory_variables({})[\"history\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`return_messages=True` 로 설정하면 `HumanMessage` 와 `AIMessage` 객체를 반환합니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "memory = ConversationBufferMemory(return_messages=True)\n",
    "\n",
    "memory.save_context(\n",
    "    inputs={\n",
    "        \"human\": \"안녕하세요, 비대면으로 은행 계좌를 개설하고 싶습니다. 어떻게 시작해야 하나요?\"\n",
    "    },\n",
    "    outputs={\n",
    "        \"ai\": \"안녕하세요! 계좌 개설을 원하신다니 기쁩니다. 먼저, 본인 인증을 위해 신분증을 준비해 주시겠어요?\"\n",
    "    },\n",
    ")\n",
    "\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"네, 신분증을 준비했습니다. 이제 무엇을 해야 하나요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"감사합니다. 신분증 앞뒤를 명확하게 촬영하여 업로드해 주세요. 이후 본인 인증 절차를 진행하겠습니다.\"\n",
    "    },\n",
    ")\n",
    "\n",
    "memory.save_context(\n",
    "    inputs={\"human\": \"사진을 업로드했습니다. 본인 인증은 어떻게 진행되나요?\"},\n",
    "    outputs={\n",
    "        \"ai\": \"업로드해 주신 사진을 확인했습니다. 이제 휴대폰을 통한 본인 인증을 진행해 주세요. 문자로 발송된 인증번호를 입력해 주시면 됩니다.\"\n",
    "    },\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# history에 저장된 대화 기록을 확인합니다.\n",
    "memory.load_memory_variables({})[\"history\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\"system\", \"당신은 친절한 AI 봇입니다\"),\n",
    "        (\"human\", \"대한민국의 수도는 어디야?\"),\n",
    "    ]\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Chain 에 적용\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# API KEY를 환경변수로 관리하기 위한 설정 파일\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "# API KEY 정보로드\n",
    "load_dotenv()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "from langchain.chains import ConversationChain\n",
    "\n",
    "# LLM 모델을 생성합니다.\n",
    "llm = ChatOpenAI(temperature=0, model_name=\"gpt-4.1-mini\")\n",
    "\n",
    "# ConversationChain을 생성합니다.\n",
    "conversation = ConversationChain(\n",
    "    # ConversationBufferMemory를 사용합니다.\n",
    "    llm=llm,\n",
    "    memory=ConversationBufferMemory(),\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`ConversationChain`을 사용하여 대화를 진행합니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 대화를 시작합니다.\n",
    "response = conversation.predict(\n",
    "    input=\"안녕하세요, 비대면으로 은행 계좌를 개설하고 싶습니다. 어떻게 시작해야 하나요?\"\n",
    ")\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "이전의 대화 기록을 기억하고 있는지 확인합니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 이전 대화내용을 불렛포인트로 정리해 달라는 요청을 보냅니다.\n",
    "response = conversation.predict(\n",
    "    input=\"이전 답변을 불렛포인트 형식으로 정리하여 알려주세요.\"\n",
    ")\n",
    "print(response)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "py-test",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
